use std::{rc::Rc, cell::RefCell, sync::{Arc, Mutex}};

use crate::{native, rtda::{Frame, ExtraType, DataType, heap::{string_pool, Class, MethodType, Method}, Object, Thread, OperandStack, LocalVars}, instructions::base::invoke_java_method};

//MemberName JVM 对 vtable 索引使用 -2 及以上的值。字段值是简单的正偏移量。参考：srcsharevmoopsmethodOop.hpp 此值为负数足以避免此类数字，但不会太负数。
const MN_IS_METHOD           :i32 = 0x00010000; // method (not constructor)
const MN_IS_CONSTRUCTOR      :i32 = 0x00020000; // constructor
const MN_IS_FIELD            :i32 = 0x00040000; // field
const MN_IS_TYPE             :i32 = 0x00080000; // nested type
const MN_CALLER_SENSITIVE    :i32 = 0x00100000; // @CallerSensitive annotation detected
const MN_REFERENCE_KIND_SHIFT:i32 = 24; // refKind
const MN_REFERENCE_KIND_MASK :i32 = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT;
// The SEARCH_* bits are not :i32 for MN.flags but for the matchFlags argument of MHN.getMembers:
const MN_SEARCH_SUPERCLASSES :i32 = 0x00100000;
const MN_SEARCH_INTERFACES   :i32 = 0x00200000;

// 常量池引用类型代码，由 CONSTANT_MethodHandle CP 条目使用。
const REF_NONE              :i32 = 0;  // null value
const REF_GET_FIELD         :i32 = 1;
const REF_GET_STATIC        :i32 = 2;
const REF_PUT_FIELD         :i32 = 3;
const REF_PUT_STATIC        :i32 = 4;
const REF_INVOKE_VIRTUAL    :i32 = 5;
const REF_INVOKE_STATIC     :i32 = 6;
const REF_INVOKE_SPECIAL    :i32 = 7;
const REF_NEW_INVOKE_SPECIAL:i32 = 8;
const REF_INVOKE_INTERFACE  :i32 = 9;
const REF_LIMIT             :i32 = 10;

pub fn init() {
    native::register("java/lang/invoke/MethodHandleNatives", "init", "(Ljava/lang/invoke/MemberName;Ljava/lang/Object;)V", _init);    
    native::register("java/lang/invoke/MethodHandleNatives", "getConstant", "(I)I", float_to_raw_int_bits);    native::register("java/lang/invoke/MethodHandleNatives", "getConstant", "(I)I", float_to_raw_int_bits);
    native::register("java/lang/invoke/MethodHandleNatives", "resolve", "(Ljava/lang/invoke/MemberName;Ljava/lang/Class;)Ljava/lang/invoke/MemberName;", resolve);

    native::register("java/lang/invoke/MethodHandleNatives", "objectFieldOffset", "(Ljava/lang/invoke/MemberName;)J", object_field_offset);


    native::register("java/lang/invoke/MethodHandleNatives", "getMembers", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Class;I[Ljava/lang/invoke/MemberName;)I", get_members);


}

// 应该是通过ref生成self，[class, methodName, methodType, flags, resolution]
// flags [5,8]为引用类型，[9,16]应该是MethodHandleNatives.java第92行定义的常量，[17,32]为成员的修饰符标志 
// 未找到生成的方法，obj为Method类对象，经测试flags最后部分(最多16位字节最少4字节)可能是obj的modifiers。
// TODO 231123 未找到flags具体是咋创建的，暂时用测试时看到的结果用名称匹配。
// static native void init(MemberName self, Object ref);
// (Ljava/lang/invoke/MemberName;Ljava/lang/Object;)V
fn _init(frame: Rc<RefCell<Frame>>) {
    let j_thread = frame.borrow().get_thread().lock().unwrap().get_j_thread();

    unsafe {
        let _self = frame.borrow().get_local_vars().borrow().get_ref(0).unwrap();
        let obj = frame.borrow().get_local_vars().borrow().get_ref(1).unwrap();
       
        let clazz = get_clazz(obj, j_thread).unwrap();
        let class = {&*clazz}.get_extra().unwrap().get_class();
        let class_name = class.get_name();
        // MemberName.flagsMods(): flags = flags[9,16] | mods[17,32] | (refKind << MN_REFERENCE_KIND_SHIFT)[1-8]
        // 暂时用用名称匹配测试时看到的结果。
        let flags = match &class_name[..] {
            "java/lang/invoke/DirectMethodHandle" => 100728840,
            "java/lang/invoke/DirectMethodHandle$Interface" => 83951616,
            "java/lang/invoke/DelegatingMethodHandle" => 83952644,
            "java/lang/invoke/Invokers" => 100728840,
            // "java/lang/invoke/MethodHandleImpl" => 100728840,
            _ => panic!("暂不支持： {}", class_name)
        };
        
        // dbg!(class.get_name());
        // dbg!(class.get_access_flags());
        // println!("access_flags: {:016b}", class.get_access_flags());
        // println!("access_flags: {:04x}", class.get_access_flags());
        // get_modifiers(obj);
        // get_root(obj);

        // setting values
        if let DataType::Slots(slots) = { &mut *_self }.get_data_mut() {
            slots.set_ref(0, Some(clazz));
            slots.set_int(3, flags);
        }
    }
}

fn get_clazz(obj: *mut Object, j_thread: Option<*mut Object>) -> Option<*mut Object> {
    let obj_class = unsafe{ &* obj }.get_class(); // java.lang.reflect.Method
    // public Class<?> getDeclaringClass()
    let method = obj_class.get_instance_method("getDeclaringClass", "()Ljava/lang/Class;").unwrap();
    
    // 创建新帧，执行方法，返回结果由shim_frame接收
    let mut vars = LocalVars::new_local_vars(method.get_max_locals());
    // 实例方法self
    vars.set_ref(0, Some(obj));

    // 执行，返回结果
    let stack = invoke_java_method(method, vars, None, j_thread);

    let clazz_obj = stack.borrow_mut().pop_ref();
    clazz_obj
}

// fn get_modifiers(obj: *mut Object) {
//     // 新建thread用来执行java方法
//     let thread = Arc::new(Mutex::new(Thread::new_thread(None)));
//     // 新建frame用来接收返回结果，通过指定类以防止一些native无法获取到当前类（例如Reflection.getCallerClass）
//     let ops = OperandStack::new_operand_stack(1);
//     let _frame = Frame::new_shim_frame(thread.clone(), Rc::new(RefCell::new(ops)));
//     let obj_class = unsafe{ &* obj }.get_class(); // java.lang.reflect.Method
//     // public Class<?> getDeclaringClass()
//     let method = obj_class.get_instance_method("getModifiers", "()I").unwrap();
    
//     // 创建新帧，执行方法，返回结果由shim_frame接收
//     let new_frame = Frame::new_frame(thread.clone(), method);
//     let new_vars = new_frame.get_local_vars();
//     // 实例方法self
//     new_vars.borrow_mut().set_ref(0, Some(obj));

//     thread.lock().unwrap().push_frame(_frame);
//     let shim_frame = thread.lock().unwrap().current_frame();
//     thread.lock().unwrap().push_frame(new_frame);

//     // 执行
//     crate::interpreter::_loop(thread.clone(), false);

//     let modifiers = shim_frame.borrow().get_operand_stack().borrow_mut().pop_int();
//     dbg!(modifiers);
//     println!("obj_class: {:016b}", modifiers);
//     println!("obj_class: {:04x}", modifiers);
// }

// fn get_root(obj: *mut Object) {
//     // 新建thread用来执行java方法
//     let thread = Arc::new(Mutex::new(Thread::new_thread(None)));
//     // 新建frame用来接收返回结果，通过指定类以防止一些native无法获取到当前类（例如Reflection.getCallerClass）
//     let ops = OperandStack::new_operand_stack(1);
//     let _frame = Frame::new_shim_frame(thread.clone(), Rc::new(RefCell::new(ops)));

//     let obj_class = unsafe{ &* obj }.get_class(); // java.lang.reflect.Method
//     // Executable getRoot()
//     let method = obj_class.get_instance_method("getRoot", "()Ljava/lang/reflect/Executable;").unwrap();
    
//     // 创建新帧，执行方法，返回结果由shim_frame接收
//     let new_frame = Frame::new_frame(thread.clone(), method);
//     let new_vars = new_frame.get_local_vars();
//     // 实例方法self
//     new_vars.borrow_mut().set_ref(0, Some(obj));

//     thread.lock().unwrap().push_frame(_frame.clone());
//     let shim_frame = thread.lock().unwrap().current_frame();
//     thread.lock().unwrap().push_frame(new_frame);

//     // 执行
//     crate::interpreter::_loop(thread.clone(), false);

//     let root = shim_frame.borrow().get_operand_stack().borrow_mut().pop_ref();
//     if let Some(root) = root {
//         get_modifiers(root);
//     }
    
//     // dbg!(modifiers);
//     // println!("obj_class: {:016b}", modifiers);
//     // println!("obj_class: {:04x}", modifiers);
// }

// TODO 231122 没找到要做什么，暂时直接返回
// 获取与 MH 相关的 JVM 参数。which=0 检索 MethodHandlePushLimit which=1 检索堆栈槽推送大小（以地址单位为单位）
// static native int getConstant(int which);
// (I)I
fn float_to_raw_int_bits(frame: Rc<RefCell<Frame>>) {
    let value = frame.borrow().get_local_vars().borrow().get_int(0); 
    frame.borrow().get_operand_stack().borrow_mut().push_int(value);
}

// 231122 应该是添加访问标志,
// 经测试（LookupTest.class文件）模拟查找String.valueOf(Object)方法，访问标志为ACC_PUBLIC和ACC_STATIC
// 返回前flags为100728832，返回后变为100728841，变化为增加了访问标志ACC_PUBLIC和ACC_STATIC
// static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
// (Ljava/lang/invoke/MemberName;Ljava/lang/Class;)Ljava/lang/invoke/MemberName;
fn resolve(frame: Rc<RefCell<Frame>>) {
    let j_thread = frame.borrow().get_thread().lock().unwrap().get_j_thread();

    unsafe {

        // _self Slots:[class(class对象), methodName(方法名称字符串), methodType(methodType对象), flags(要修改的int), resolution(引用自身，暂时无用)]
        let _self = frame.borrow().get_local_vars().borrow().get_ref(0).unwrap();
        // 调用方法的class，
        let caller = frame.borrow().get_local_vars().borrow().get_ref(1);

        // println!("{}", { &*_self });
        if let DataType::Slots(slots) = { &mut *_self }.get_data_mut() {
            let class = { &*slots.get_ref(0).unwrap() }.get_extra().unwrap().get_class();
            // dbg!(class.get_name());

            let name_obj = slots.get_ref(1).unwrap();
            let name = string_pool::rs_string(name_obj);
            // dbg!(name.clone());

            let mt_obj = slots.get_ref(2).unwrap();
            if &{&*mt_obj}.get_class().get_name() == "java/lang/Class" {
                // Class 查找字段
                // dbg!(class.get_instance_slot_count());
                // dbg!(class.get_static_slot_count());
                let filed = Class::get_field_by_name(Some(class), &name);
                // dbg!(filed.as_ref().unwrap().get_slot_id());
                // dbg!(method.get_access_flags());
                let assess_flags = filed.unwrap().get_access_flags() as i32;
                let flags = slots.get_int(3);
                // dbg!(assess_flags | flags);
                slots.set_int(3, flags | assess_flags);
                
                // panic!("cc")
            } else {
                // MethodType 查找方法
                let descriptor = method_type_to_descriptor(mt_obj, caller, j_thread);
                // dbg!(descriptor.clone());
    
                let mut method = class.get_method_any(&name, &descriptor);
                if method.is_none() {
                    // 为空尝试查找参数为Object数组的
                    // let last_paren = descriptor.rfind(')').unwrap();
                    // let new_descriptor = "([Ljava/lang/Object;)".to_string() + &descriptor[last_paren+1..];
                    // dbg!(new_descriptor.clone());
                    // 为空尝试仅通过名称查找
                    method = class.get_method_by_name(&name);
                    // panic!(":sdf");
                }
                // dbg!(method.get_access_flags());
                let assess_flags = method.unwrap().get_access_flags() as i32;
                let flags = slots.get_int(3);
                // dbg!(assess_flags | flags);
                slots.set_int(3, flags | assess_flags);
            }
            
        }
        // panic!("sdfdsf");
        frame.borrow().get_operand_stack().borrow_mut().push_ref(Some(_self));
    }
}

fn method_type_to_descriptor(mt: *mut Object, caller: Option<*mut Object>, j_thread: Option<*mut Object>) -> String {
    // 调用者class，为空用shim替代
    let caller_class = match caller {
        Some(obj) => unsafe{ &*obj }.get_extra().unwrap().get_class(),
        None => Arc::new(Class::new_shim())
    };

    let mt_class = unsafe{ &* mt }.get_class();
    // public String toMethodDescriptorString()
    let method = mt_class.get_instance_method("toMethodDescriptorString", "()Ljava/lang/String;").unwrap();
    
    // 创建新帧，执行方法，返回结果由shim_frame接收
    // let new_frame = Frame::new_frame(thread.clone(), method);
    let mut vars = LocalVars::new_local_vars(method.get_max_locals());
    // 实例方法self
    vars.set_ref(0, Some(mt));

    // 执行，返回结果
    let stack = invoke_java_method(method, vars, Some(caller_class), j_thread);

    let descriptor_obj = stack.borrow_mut().pop_ref();
    string_pool::rs_string(descriptor_obj.unwrap())
}

// 应该是返回slotId，未测试
// static native long objectFieldOffset(MemberName self);  // e.g., returns vmindex
// (Ljava/lang/invoke/MemberName;)J
fn object_field_offset(frame: Rc<RefCell<Frame>>) {
    unsafe {
        // _self Slots:[class(class对象), methodName(方法名称字符串), methodType(methodType对象), flags(要修改的int), resolution(引用自身，暂时无用)]
        let _self = frame.borrow().get_local_vars().borrow().get_ref(0).unwrap();
        // 调用方法的class，
        // let caller = frame.borrow().get_local_vars().borrow().get_ref(1);

        if let DataType::Slots(slots) = { &mut *_self }.get_data() {
            let class = { &*slots.get_ref(0).unwrap() }.get_extra().unwrap().get_class();

            let name_obj = slots.get_ref(1).unwrap();
            let name = string_pool::rs_string(name_obj);

            let mt_obj = slots.get_ref(2).unwrap();
            // Class 查找字段
            let filed = Class::get_field_by_name(Some(class), &name);
            let slot_id = filed.unwrap().get_slot_id() as i64;
               
            frame.borrow().get_operand_stack().borrow_mut().push_long(slot_id);
        }  
    }
}

// 应该是将defc中的方法填充到results中，返回方法总数-skip, matchFlags应该是flags[9,16]。别的参数不知道有什么用
// static native int getMembers(Class<?> defc, String matchName, String matchSig, int matchFlags, Class<?> caller, int skip, MemberName[] results);
// (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Class;I[Ljava/lang/invoke/MemberName;)I
pub fn get_members(frame: Rc<RefCell<Frame>>) {
    let j_thread = frame.borrow().get_thread().lock().unwrap().get_j_thread();

    unsafe {
        let defc = frame.borrow().get_local_vars().borrow().get_ref(0).unwrap();
        let class = { &*defc }.get_extra().unwrap().get_class();
        let loader = class.get_class_loader().unwrap();
        // dbg!(class.get_name());
        let match_flags = frame.borrow().get_local_vars().borrow().get_int(3);
        // dbg!(match_flags);
        let skip = frame.borrow().get_local_vars().borrow().get_int(5) as usize;
        // dbg!(skip);
        let results = frame.borrow().get_local_vars().borrow().get_ref(6).unwrap();
        let mut arr = { &mut *results }.array().refs();
        let arr_len = arr.len();
        // dbg!(arr);

        // 填充results [class, methodName, methodType, flags, resolution]
        let methods = class.get_declared_methods();
        for i in 0..arr_len {
            let method = &methods[skip + i];
            if let DataType::Slots(slots) = { &mut *arr[i].unwrap() }.get_data_mut() {
                slots.set_ref(0, Some(defc));

                let name = string_pool::j_string(&mut loader.lock().unwrap(), &method.get_name());
                slots.set_ref(1, Some(name));

                // TODO 231124 可能会有很多重复的method_type，后续可通过map来存储
                let method_type = MethodType::create_method_type(loader.clone(), &method.get_descriptor(), j_thread);
                slots.set_ref(2, method_type);

                let access_flags = method.get_access_flags() as i32;
                let ref_kind = get_ref_kind(method);
                // MemberName.flagsMods(): flags = flags[9,16] | mods[17,32] | (refKind << MN_REFERENCE_KIND_SHIFT)[1-8]
                let flags = match_flags | access_flags | (ref_kind << MN_REFERENCE_KIND_SHIFT);
                slots.set_int(3, flags);

                slots.set_ref(4, None);
            } else {
                panic!("TO DO")
            }
        }

        // 返回结果
        frame.borrow().get_operand_stack().borrow_mut().push_int((methods.len() - skip) as i32);
    }

    // panic!("cccdddeeefff");
}

// 通过方法判断refKind,不知道具体是咋转换,先简单写一下
fn get_ref_kind(method: &Arc<Method>) -> i32 {
    if method.is_static() {
        return REF_INVOKE_STATIC;
    } else if method.is_private() {
        return REF_INVOKE_SPECIAL;
    } else {
        return REF_INVOKE_VIRTUAL;
    }
}